# coding: utf-8

import pandas as pd
from pandas import Series, DataFrame
import numpy as np

from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC, LinearSVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB

titanic_train = pd.read_csv("E:/data/titanic/train.csv")
titanic_test = pd.read_csv("E:/data/titanic/test.csv")

# 打印基本字段信息
print(titanic_train.head())
print(titanic_train.info())
print("-"*30)
print(titanic_test.info())

# print(titanic_train[titanic_train["Survived"]>0]["Survived"])
# titanic_train[titanic_train["Survived"].isnull]

# 去除无关字段
titanic_train = titanic_train.drop(["PassengerId", "Name", "Ticket"], axis=1)
titanic_test = titanic_test.drop(["Name", "Ticket"], axis=1)
print(titanic_train["Embarked"].value_counts())

# 填充空字段
titanic_train["Embarked"].fillna("S", inplace=True)

# 获取某字段统计值
embarked_avg = titanic_train[["Embarked", "Survived"]].groupby(["Embarked"], as_index=False).mean()
print(embarked_avg)
print("-"*30)

# one hot coded
embarked_one_hot_train = pd.get_dummies(titanic_train["Embarked"])
# print(embarked_one_hot_train)
embarked_one_hot_train.drop(["S"], axis=1, inplace=True)
embarked_one_hot_test = pd.get_dummies(titanic_test["Embarked"])
embarked_one_hot_test.drop(["S"], axis=1, inplace=True)

# 将one hot coded编码字段加入原数据(每个值成为一列)
titanic_train = titanic_train.join(embarked_one_hot_train)
titanic_test = titanic_test.join(embarked_one_hot_test)
# print(titanic_train.head())

titanic_train.drop(["Embarked"], axis=1, inplace=True)
titanic_test.drop(["Embarked"], axis=1, inplace=True)

# 在测试集中有一个缺省值，用中位数填充
print(titanic_test[titanic_test["Fare"].isnull()])
print("-"*30)
titanic_test["Fare"].fillna(titanic_test["Fare"].median(), inplace=True)

titanic_train["Fare"] = titanic_train["Fare"].astype(int)
titanic_test["Fare"] = titanic_test["Fare"].astype(int)

# 非存活的Fare分布、存活的Fare分布...
fare_not_survived = titanic_train["Fare"][titanic_train["Survived"] == 0]
# 等于 titanic_train[titanic_train["Survived"] == 0]["Fare"]
fare_survived = titanic_train["Fare"][titanic_train["Survived"] == 1]

fare_average = DataFrame([fare_not_survived.mean(), fare_survived.mean()])
fare_std = DataFrame([fare_not_survived.std(), fare_survived.std()])
fare_average.index.names = fare_std.index.names = ["Survived"]

# 年龄字段处理：null字段处理
train_age_average = titanic_train["Age"].mean()
train_age_std = titanic_train["Age"].std()
train_age_nan_count = titanic_train["Age"].isnull().sum()

test_age_average = titanic_test["Age"].mean()
test_age_std = titanic_test["Age"].std()
test_age_nan_count = titanic_test["Age"].isnull().sum()

train_age_rand = np.random.randint(low=train_age_average - train_age_std, high=train_age_average + train_age_std,
                                   size=train_age_nan_count)
test_age_rand = np.random.randint(low=test_age_average - test_age_std, high=test_age_average + test_age_std,
                                  size=test_age_nan_count)

titanic_train.loc[titanic_train["Age"].isnull(), "Age"] = train_age_rand
# equal to titanic_train["Age"][titanic_train["Age"].isnull()] = train_age_rand
titanic_test.loc[titanic_test["Age"].isnull(), "Age"] = test_age_rand
titanic_train["Age"] = titanic_train["Age"].astype(int)
titanic_test["Age"] = titanic_test["Age"].astype(int)

# 去除Cabin字段（包含太多Nan）
titanic_train.drop("Cabin", axis=1, inplace=True)
titanic_test.drop("Cabin", axis=1, inplace=True)

titanic_train["Family"] = titanic_train["Parch"] + titanic_train["SibSp"]
titanic_train.loc[titanic_train["Family"] > 0, "Family"] = 1
titanic_train.loc[titanic_train["Family"] == 0, "Family"] = 0

titanic_test["Family"] = titanic_test["Parch"] + titanic_test["SibSp"]
titanic_test.loc[titanic_test["Family"] > 0, "Family"] = 1
titanic_test.loc[titanic_test["Family"] == 0, "Family"] = 0

titanic_train.drop(["Parch", "SibSp"], axis=1, inplace=True)
titanic_test.drop(["Parch", "SibSp"], axis=1, inplace=True)

train_family_survived = titanic_train[["Family", "Survived"]].groupby(["Family"], as_index=False).mean()

# 性别
def get_person(passenger):
    age, sex = passenger
    return "child" if age < 16 else sex

titanic_train["Person"] = titanic_train[["Age", "Sex"]].apply(get_person, axis=1)
titanic_test["Person"] = titanic_test[["Age", "Sex"]].apply(get_person, axis=1)

titanic_train.drop(["Sex"], axis=1, inplace=True)
titanic_test.drop(["Sex"], axis=1, inplace=True)

train_person_one_hot = pd.get_dummies(titanic_train["Person"])
train_person_one_hot.columns = ["Child", "Female", "Male"]
train_person_one_hot.drop(["Male"], axis=1, inplace=True)

test_person_one_hot = pd.get_dummies(titanic_test["Person"])
test_person_one_hot.columns = ["Child", "Female", "Male"]
test_person_one_hot.drop(["Male"], axis=1, inplace=True)

titanic_train = titanic_train.join(train_person_one_hot)
titanic_test = titanic_test.join(test_person_one_hot)

train_person_survived = titanic_train[["Person", "Survived"]].groupby(["Person"], as_index=False).mean()

titanic_train.drop(["Person"], axis=1, inplace=True)
titanic_test.drop(["Person"], axis=1, inplace=True)

# Pclass
train_pclass_one_hot = pd.get_dummies(titanic_train["Pclass"])
train_pclass_one_hot.columns = ["Class_1", "Class_2", "Class_3"]
train_pclass_one_hot.drop(["Class_3"], axis=1, inplace=True)

test_pclass_one_hot = pd.get_dummies(titanic_test["Pclass"])
test_pclass_one_hot.columns = ["Class_1", "Class_2", "Class_3"]
test_pclass_one_hot.drop(["Class_3"], axis=1, inplace=True)

titanic_train.drop(["Pclass"], axis=1, inplace=True)
titanic_test.drop(["Pclass"], axis=1, inplace=True)

titanic_train = titanic_train.join(train_pclass_one_hot)
titanic_test = titanic_test.join(test_pclass_one_hot)


X_train = titanic_train.drop(["Survived"], axis=1)
Y_train = titanic_train["Survived"]
X_test = titanic_test.drop(["PassengerId"], axis=1).copy()

# 逻辑回归
logreg = LogisticRegression()
logreg.fit(X_train, Y_train)
Y_predict = logreg.predict(X_test)
print(logreg.score(X_train, Y_train))

# svc
svc = SVC()
svc.fit(X_train, Y_train)
Y_predict = svc.predict(X_test)
print(svc.score(X_train, Y_train))

# 随机森林
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)
Y_predict = random_forest.predict(X_test)
print(random_forest.score(X_train, Y_train))

# knn
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, Y_train)
Y_pred = knn.predict(X_test)
print(knn.score(X_train, Y_train))

# nb
gaussian = GaussianNB()
gaussian.fit(X_train, Y_train)
Y_pred = gaussian.predict(X_test)
print(gaussian.score(X_train, Y_train))

coeff_df = DataFrame(titanic_train.columns.delete(0))
coeff_df.columns = ["Features"]
coeff_df["Coefficient Estimate"] = pd.Series(logreg.coef_[0])

print(coeff_df)

submission = pd.DataFrame({
        "PassengerId": titanic_test["PassengerId"],
        "Survived": Y_pred
    })
submission.to_csv('titanic.csv', index=False)